Android

您所在的位置:网站首页 NFC 读取器 hscode Android

Android

2024-01-15 06:02| 来源: 网络整理| 查看: 265

一、NFC  API

API地址:https://www.android-doc.com/guide/topics/connectivity/nfc/nfc.html

二、简介

NFC的三种模式

读卡器模式(Reader/writer mode)、仿真卡模式(Card Emulation Mode)、点对点模式(P2P mode)。

(1)读卡器模式

数据在NFC芯片中,可以简单理解成“刷标签”。本质上就是通过支持NFC的手机或其它电子设备从带有NFC芯片的标签、贴纸、名片等媒介中读写信息。通常NFC标签是不需要外部供电的。当支持NFC的外设向NFC读写数据时,它会发送某种磁场,而这个磁场会自动的向NFC标签供电。

(2)仿真卡模式

数据在支持NFC的手机或其它电子设备中,可以简单理解成“刷手机”。本质上就是将支持NFC的手机或其它电子设备当成借记卡、公交卡、门禁卡等IC卡使用。基本原理是将相应IC卡中的信息凭证封装成数据包存储在支持NFC的外设中 。

在使用时还需要一个NFC射频器(相当于刷卡器)。将手机靠近NFC射频器,手机就会接收到NFC射频器发过来的信号,在通过一系列复杂的验证后,将IC卡的相应信息传入NFC射频器,最后这些IC卡数据会传入NFC射频器连接的电脑,并进行相应的处理(如电子转帐、开门等操作)。

(3)点对点模式

该模式与蓝牙、红外差不多,用于不同NFC设备之间进行数据交换,不过这个模式已经没有有“刷”的感觉了。其有效距离一般不能超过4厘米,但传输建立速度要比红外和蓝牙技术快很多,传输速度比红外块得多,如过双方都使用Android4.2,NFC会直接利用蓝牙传输。这种技术被称为Android Beam。所以使用Android Beam传输数据的两部设备不再限于4厘米之内。

点对点模式的典型应用是两部支持NFC的手机或平板电脑实现数据的点对点传输,例如,交换图片或同步设备联系人。因此,通过NFC,多个设备如数字相机,计算机,手机之间,都可以快速连接,并交换资料或者服务。

二、NDEF,TECH,TAG 解析顺序

在使用之前,我们要先去了解下NFC 的tag分发系统

如果想让android设备感应到NFC标签,你要保证两点 1:屏幕没有锁住 2:NFC功能已经在设置中打开 当系统检测到一个NFC标签的时候,他会自动去寻找最合适的activity去处理这个intent. 他所发出的这个Intent将会有三种action: ACTION_NDEF_DISCOVERED:当系统检测到tag中含有NDEF格式的数据时,且系统中有activity声明可以接受包含NDEF数据的Intent的时候,系统会优先发出这个action的intent。 ACTION_TECH_DISCOVERED:当没有任何一个activity声明自己可以响应ACTION_NDEF_DISCOVERED时,系统会尝试发出TECH的intent.即便你的tag中所包含的数据是NDEF的,但是如果这个数据的MIME type或URI不能和任何一个activity所声明的想吻合,系统也一样会尝试发出tech格式的intent,而不是NDEF. ACTION_TAG_DISCOVERED:当系统发现前两个intent在系统中无人会接受的时候,就只好发这个默认的TAG类型的

3:NFC标签过滤 在activity的intent过滤xml声明中,你可以同时声明过滤这三种action.但是由之前所说,你应该知道系统在发送intent的时候是有优先级的,所以你最好清楚自己最想处理哪个。 1、过滤ACTION_TAG_DISCOVERED:

2、过滤ACTION_NDEF_DISCOVERED:

data的mimeType类型了,这个定义的越准确,intent指向你这个activity的成功率就越高,否则系统可能不会发出你想要的NDEF intent了。

3、过滤ACTION_TECH_DISCOVERED: 你首先需要在你的/res/xml下面创建一个过滤规则文件。名字任取,比如可以叫做nfc_tech_filter.xml。这个里面定义的是nfc实现的各种标准,每一个nfc卡都会符合多个不同的标准,个人理解为这些标准有些相互之间也是兼容的。你可以在检测到nfc标签后使用getTechList()方法来查看你所检测的tag到底支持哪些nfc标准。 一个nfc_tech_filter.xml中可以定义多个结构组。每一组代表我声明我只接受同时满足这些标准的nfc标签。比如A组表示,只有同时满足IsoDep,NfcA,NfcB,NfcF这四个标准的nfc标签的intent才能进入。A与B组之间的关系就是只要满足其中一个就可以了。换句话说,你的nfc标签技术,满足A的声明也可以,满足B的声明也可以。

--------------------------------A组 android.nfc.tech.IsoDep android.nfc.tech.NfcA android.nfc.tech.NfcB android.nfc.tech.NfcF -----------------------------------------B组 android.nfc.tech.NfcV android.nfc.tech.Ndef android.nfc.tech.NdefFormatable android.nfc.tech.MifareClassic android.nfc.tech.MifareUltralight

过滤器过滤

4、

nfc标签前台分发系统 之所以把他也归类在nfc的过滤里面,主要是因为他跟解析nfc标签到不是那么的紧密,他解决的是接受哪些nfc标准的标签问题。所以更接近nfc的过滤。 什么叫nfc的前台发布系统?就是说当我们已经打开我们的应用的时候,那么通过这个前台发布系统的设置,我们可以让我们已经启动的activity拥有更高的优先级来依据我们在代码中定义的标准来过滤和处理intent,而不是让别的声明了intent filter的activity来干扰,甚至连自己声明在androidManifest中的intent filter都不会来干扰。也就是说foreground Dispatch的优先级大于intent filter。 第一种情况:当你的activity没有启动的时候,去扫描tag,那么系统中所有的intent filter都将一起参与过滤。 第二种情况:当你的actiity启动了,去扫描tag时,那么将直接使用你在foreground dispatch中代码写入的过滤标准。如果这个标准没有命中任何intent,那么系统将使用所有activity声明的intent filter xml来过滤。

三、NFC有关的常见的ISO标准有:

标准说明ISO 14443RFID卡标准(非接触IC卡),该标准又有很多子标准ISO 7816接触式IC卡标准ISO 15693某种射频卡标准吧,这个没查到资料ISO 18092NFC标准

 四、使用

1、加权限

2、加上文提到的过滤,将activity启动模式android:launchMode="singleInstance"或者android:launchMode="singleTop"

3、封装工具类

/** * Created by Administrator on 2019/7/26 *

* desc: */ public class nfcUtils { public static NfcAdapter mNfcAdapter; public static IntentFilter[] mIntentFilter = null; public static PendingIntent mPendingIntent = null; public static String[][] mTechList = null; /** * 构造函数,用于初始化nfc */ public nfcUtils(Activity activity) { mNfcAdapter = isNfcEnable(activity); NfcInit(activity); } /** * 判断手机是否具备NFC功能 * * @param context {@link Context} * @return {@code true}: 具备 {@code false}: 不具备 */ public static boolean isNfcExits(Context context) { NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(context); return nfcAdapter != null; } /** * 判断手机NFC是否开启 *

* OPPO A37m 发现必须同时开启NFC以及Android Beam才可以使用 * 20180108 发现OPPO单独打开NFC即可读取标签,不清楚是否是系统更新 *

* * @param context {@link Context} * @return {@code true}: 已开启 {@code false}: 未开启 */ public static boolean isNfcEnable(Context context) { NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(context); // if (Build.MANUFACTURER.toUpperCase().contains("OPPO")) { // return nfcAdapter.isEnabled() && isAndroidBeamEnable(context); // } return nfcAdapter != null && nfcAdapter.isEnabled(); } /** * 判断手机NFC的Android Beam是否开启,在API 16之后才有 * * @param context {@link Context} * @return {@code true}: 已开启 {@code false}: 未开启 */ public static boolean isAndroidBeamEnable(Context context) { NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(context); return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && nfcAdapter != null && nfcAdapter.isNdefPushEnabled(); } /** * 判断手机是否具备Android Beam * * @param context {@link Context} * @return {@code true}:具备 {@code false}:不具备 */ public static boolean isAndroidBeamExits(Context context) { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && isNfcExits(context); } /** * 跳转至系统NFC设置界面. * * @param context {@link Context} * @return {@code true} 跳转成功 {@code false} 跳转失败 */ public static boolean intentToNfcSetting(Context context) { if (isNfcExits(context)) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { return toIntent(context, Settings.ACTION_NFC_SETTINGS); } } return false; } /** * 跳转至系统NFC Android Beam设置界面,同页面基本都有NFC开关. * * @param context {@link Context} * @return {@code true} 跳转成功 {@code false} 跳转失败 */ public static boolean intentToNfcShare(Context context) { if (isAndroidBeamExits(context)) { return toIntent(context, Settings.ACTION_NFCSHARING_SETTINGS); } return false; } /** * 跳转方法. * @param context {@link Context} * @param action 意图 * @return 是否跳转成功 {@code true } 成功{@code false}失败 */ private static boolean toIntent(Context context, String action) { try { Intent intent = new Intent(action); context.startActivity(intent); } catch (Exception ex) { ex.printStackTrace(); return false; } return true; } /** * 初始化nfc设置 */ public static void NfcInit(Activity activity) { 方法一: Intent intent = new Intent(activity, activity.getClass()); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); mPendingIntent = PendingIntent.getActivity(activity, 0, intent, 0); //做一个IntentFilter过滤你想要的action 这里过滤的是ndef IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); //如果你对action的定义有更高的要求,比如data的要求,你可以使用如下的代码来定义intentFilter // IntentFilter filter2 = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); // try { // filter.addDataType("*/*"); // } catch (IntentFilter.MalformedMimeTypeException e) { // e.printStackTrace(); // } // mIntentFilter = new IntentFilter[]{filter, filter2}; // mTechList = null; try { filter.addDataType("*/*"); } catch (IntentFilter.MalformedMimeTypeException e) { e.printStackTrace(); } mTechList = new String[][]{{MifareClassic.class.getName()}, {NfcA.class.getName()}}; //生成intentFilter mIntentFilter = new IntentFilter[]{filter}; 方法二: mPendingIntent = PendingIntent.getActivity(activity, 0, new Intent(activity, activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); IntentFilter filter2 = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); try { filter.addDataType("*/*"); } catch (IntentFilter.MalformedMimeTypeException e) { e.printStackTrace(); } mIntentFilter = new IntentFilter[]{filter, filter2}; mTechList = null; } /** * 读取NFC的数据 */ public static String readNFCFromTag(Intent intent) throws UnsupportedEncodingException { Parcelable[] rawArray = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawArray != null) { NdefMessage mNdefMsg = (NdefMessage) rawArray[0]; NdefRecord mNdefRecord = mNdefMsg.getRecords()[0]; if (mNdefRecord != null) { String readResult = new String(mNdefRecord.getPayload(), "UTF-8"); return readResult; } } return ""; } /** * 往nfc写入数据 */ public static void writeNFCToTag(String data, Intent intent) throws IOException, FormatException { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); Ndef ndef = Ndef.get(tag); ndef.connect(); NdefRecord ndefRecord = null; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { ndefRecord = NdefRecord.createTextRecord(null, data); } NdefRecord[] records = {ndefRecord}; NdefMessage ndefMessage = new NdefMessage(records); ndef.writeNdefMessage(ndefMessage); } /** * 读取nfcID */ public static String readNFCId(Intent intent) throws UnsupportedEncodingException { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); String id = ByteArrayToHexString(tag.getId()); return id; } /** * 将字节数组转换为字符串 */ private static String ByteArrayToHexString(byte[] inarray) { int i, j, in; String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}; String out = ""; for (j = 0; j < inarray.length; ++j) { in = (int) inarray[j] & 0xff; i = (in >> 4) & 0x0f; out += hex[i]; i = in & 0x0f; out += hex[i]; } return out; } }

4、弹框提示

private void showDialog(String title, String content, View.OnClickListener listener) { dismissDialog(); AlertDialog.Builder builder = new AlertDialog.Builder(this); LayoutInflater inflater = LayoutInflater.from(this); View view = inflater.inflate(R.layout.dialog_tag_lost, null); TextView tvTitle = (TextView) view.findViewById(R.id.dialog_title); TextView tvContent = (TextView) view.findViewById(R.id.dialog_content); tvTitle.setText(title); tvContent.setText(content); Button btnCancel = (Button) view.findViewById(R.id.btn_cancel); Button btnOk = (Button) view.findViewById(R.id.btn_confirm); btnCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismissDialog(); } }); btnOk.setOnClickListener(listener); builder.setView(view); mDialog = builder.create(); mDialog.setCancelable(false); mDialog.setCanceledOnTouchOutside(false); mDialog.show(); } private void dismissDialog() { if (mDialog != null && mDialog.isShowing()) { mDialog.dismiss(); mDialog = null; } }

 

5、生命周期

@Override protected void onDestroy() { super.onDestroy(); dismissDialog(); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); processIntent(intent); } public void onResume(){ super.onResume(); nfcUtils.mNfcAdapter.enableForegroundDispatch(this, nfcUtils.mPendingIntent, nfcUtils.mIntentFilter, nfcUtils.mTechList); } public void onPause(){ super.onPause(); if (nfcUtils.isNfcEnable(this)){ nfcUtils.mNfcAdapter.disableForegroundDispatch(this); } }

 6、在onCreate()中    nfcUtils nfc = new NFC(this);

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3